package QC.MessageBox.service;

import QC.MessageBox.beans.appmsg.ImageInfo;
import QC.MessageBox.common.Constants;
import QC.MessageBox.exceptions.HttpClientException;
import io.vertx.core.Future;
import io.vertx.core.Vertx;
import io.vertx.core.json.JsonObject;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.RandomAccessFile;
import java.net.URL;
import java.net.URLConnection;

/**
 * Created by Andaren on 2017/5/12.
 * Used for: 执行阻塞代码
 */
public class BlockingService {

    public static final Logger LOGGER = LoggerFactory.getLogger(BlockingService.class);

    private Vertx vertx;

    public BlockingService(Vertx vertx) {
        this.vertx = vertx;
    }

    /**
     * 下载媒体文件
     * @param mediaUrl
     * @return
     */
    public Future<File> createFileFromUrl(String mediaUrl) {
        Future<File> mediaFileFut =  Future.future();
        vertx.executeBlocking(fileFut -> {
            try {
                // http://mmbiz.qpic.cn/mmbiz_jpg/thr6icdLqafox1DicicDrMia8QdIVWELSictiaMibj91aRIlzp5iaBBDcRhLVDdI2KmlwibQC3BEUFus2ia7vSia1nyNdfuCA/0
                URL url = new URL(mediaUrl);
                DataInputStream dataInputStream = new DataInputStream(url.openStream());
                File newFile = new File(System.currentTimeMillis() + ".jpg");
                RandomAccessFile af = new RandomAccessFile(newFile, "rw");
                int nb;
                while((nb = dataInputStream.read()) >= 0) {
                    af.writeByte(nb);
                }
                dataInputStream.close();
                af.close();
                fileFut.complete(newFile);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }, result -> {
            if(result.failed()) {
                mediaFileFut.fail(result.cause());
            } else {
                mediaFileFut.complete((File)result.result());
            }
        });
        return mediaFileFut;
    }

    /**
     * 同步上传永久素材
     * @param accessToken
     * @param file
     * @param type
     * @return
     */
    public Future<String> synUploadPermanentMediaByHttpClient4(String accessToken, File file, String type) {
        Future<String> mediaIdFut =  Future.future();
        vertx.executeBlocking(fileFut -> {
            try {
                HttpClient httpClient = HttpClients.createDefault();

                StringBuilder urlSb = new StringBuilder();
                urlSb.append(Constants.WX_INTERFACE_HOST_PROXY)
                        .append("/cgi-bin")
                        .append("/material/add_material")
                        .append("?access_token=").append(accessToken)
                        .append("&type=").append(type);
                if (file == null || !file.exists()) {
                    throw new FileNotFoundException();
                }
                if ("image".equals(type) && file.length() > (64 * 1024)) {
                    throw new HttpClientException("picture size too large [" + file.length() + "] when allow size is [" + (60*1024) + "]");
                }
                MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();
                multipartEntityBuilder
                        .addBinaryBody("media", file)
                        .setMode(HttpMultipartMode.RFC6532);
                HttpPost httpPost = new HttpPost(urlSb.toString());
                httpPost.setEntity(multipartEntityBuilder.build());
                httpPost.setHeader("Content-Type", ContentType.MULTIPART_FORM_DATA.toString());
                HttpResponse httpResponse = httpClient.execute(httpPost);
                HttpEntity httpEntity =  httpResponse.getEntity();
                String content = EntityUtils.toString(httpEntity);
                LOGGER.info("[同步上传永久素材返回]->{}", content);
                fileFut.complete(content);
            } catch (Exception e) {
                e.printStackTrace();
                mediaIdFut.fail(e.getMessage());
            }
        }, result -> {
            if(result.failed()) {
                mediaIdFut.fail(result.cause());
            } else {
                JsonObject mediaJson = new JsonObject(String.valueOf(result.result()));
                if (mediaJson.getString("media_id") == null) {
                    mediaIdFut.fail(mediaJson.encodePrettily());
                } else {
                    mediaIdFut.complete(mediaJson.getString("media_id"));
                }
            }
        });
        return mediaIdFut;
    }

    /**
     * 从url中找到url对应html的标题元素
     * @param url
     * @return
     */
    public Future<String> getTitleFromURL(String url) {
        Future<String> titleFut =  Future.future();
        vertx.executeBlocking(fileFut -> {
            try {
                Document doc = Jsoup.connect(url).get();
                String title = doc.title();
                LOGGER.info("url中获取到标题 :{}", title);
                fileFut.complete(title);
            } catch (Exception e) {
                e.printStackTrace();
                titleFut.fail(e.getMessage());
            }
        }, result -> {
            if(result.failed()) {
                titleFut.fail(result.cause());
            } else {
                titleFut.complete(String.valueOf(result.result()));
            }
        });
        return titleFut;
    }

    public Future<ImageInfo> getImageInfoByUrl (String imageUrl) {
        Future<ImageInfo> imageInfoFuture = Future.future();
        vertx.executeBlocking(imageFut -> {
            try {
                URL url = new URL(imageUrl);
                URLConnection connection = url.openConnection();
                connection.setDoOutput(true);
                BufferedImage image = ImageIO.read(connection.getInputStream());
                ImageInfo imageInfo = new ImageInfo();
                imageInfo.setUrl(imageUrl)
                        .setHeight(image.getHeight())
                        .setWidth(image.getWidth());
                imageFut.complete(imageInfo);
            }
            catch (Exception e) {
                e.printStackTrace();
                imageFut.fail(e.getCause());
            }
        }, result -> {
            if(result.failed()) {
                imageInfoFuture.fail(result.cause());
            } else {
                imageInfoFuture.complete((ImageInfo) result.result());
            }
        });
        return imageInfoFuture;
    }

    public Future<Void> sleep(Long millins) {
        Future<Void> sleepFut =  Future.future();
        vertx.executeBlocking(sleep -> {
            try {
                Thread.sleep(millins);
                sleep.complete();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }, retureAr ->{
            sleepFut.complete();
        });
        return sleepFut;
    }
}
